package com.flex.core.web;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.springframework.beans.factory.annotation.Autowired;

import com.flex.constants.SystemConstants;
import com.flex.core.freeMarker.FreeMarkerEngine;
import com.flex.core.helper.ApplicationHelper;
import com.flex.core.model.AbstractIdEntity;
import com.flex.core.utils.CookieUtils;
import com.flex.core.utils.JsonUtils;
import com.flex.core.validate.ValidateManager;
import com.flex.core.web.result.ChainResult;
import com.flex.core.web.result.DispatcherResult;
import com.flex.core.web.result.RedirectResult;
import com.flex.core.web.result.StringResult;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.inject.Inject;

/**
 * 所有action的基类，扩展了很多辅助action操作的方法
 * 
 * @author radio
 * 
 */
public class BaseActionSupport extends ActionSupport {

	private static final long serialVersionUID = 5208748057591198755L;

	protected ActionMapper actionMapper;

	@Inject
	public void setActionMapper(ActionMapper mapper) {
		this.actionMapper = mapper;
	}

	@Autowired
	private FreeMarkerEngine freeMarkerEngine;

	@Autowired
	private ValidateManager validateManager;

	/**
	 * 获取servletContext
	 * 
	 * @return
	 */
	protected ServletContext getServletContext() {
		return ServletActionContext.getServletContext();
	}

	/**
	 * 获得request的method，是POST还是GET还是其他方法
	 * 
	 * @return
	 */
	protected String getMethod() {
		return getRequest().getMethod().toUpperCase();
	}

	/**
	 * 存储cookie的方法
	 * 
	 * @param key
	 * @param value
	 */
	public void addCookie(String key, String value) {
		if (!ApplicationHelper.isBlank(key)
				&& !ApplicationHelper.isBlank(value)) {
			CookieUtils.setCookie(getRequest(), getResponse(), key, value
					.replace("@", ","), SystemConstants.COOKIE_MAX_AGE);
		}
	}

	/**
	 * 清楚用户的cookie信息
	 * 
	 * @param key
	 */
	public void clearCookie(String key) {
		if (!ApplicationHelper.isBlank(key)) {
			CookieUtils.setCookie(getRequest(), getResponse(), key, null, 0);
		}
	}

	/**
	 * 获取HttpServletRequest
	 * 
	 * @return
	 */
	protected HttpServletRequest getRequest() {
		return ServletActionContext.getRequest();
	}

	/**
	 * 获取HttpServletResponse
	 * 
	 * @return
	 */
	protected HttpServletResponse getResponse() {
		return ServletActionContext.getResponse();
	}

	/**
	 * 获得HttpSession，如果SESSION_CLUSTERID为true,则使用HttpSessionWrapper来构建HttpSession获得session集群的特性
	 * 
	 * @see HttpSessionWrapper
	 */
	protected HttpSession getSession() {
		return getRequest().getSession();
	}

	/**
	 * 将数据存入ActionContext中，供页面显示
	 * 
	 * @param key
	 *            页面调用的值 ${key}
	 * @param value
	 *            与key对应的数据
	 */
	protected void putObjToContext(String key, Object value) {
		ActionContext.getContext().put(key, value);
	}

	/**
	 * 从ActionContext中取得对象数据
	 * 
	 * @param key
	 *            ActionContext中的key
	 * @return 与key对应的value
	 */
	protected Object getObjFromContext(String key) {
		return ActionContext.getContext().get(key);
	}

	/**
	 * 将action中的消息显示到页面，消息码保存在messageMap的message中
	 * 
	 * @param value
	 *            要显示的消息码
	 */
	@SuppressWarnings("unchecked")
	protected void displayMsg(String value) {
		if (!value.equals("")) {
			HashMap<String, String> map = (HashMap<String, String>) getObjFromContext("messageMap");
			if (map == null || map.keySet().size() == 0) {
				map = new HashMap<String, String>();
			}
			map.put("message", value);
			putObjToContext("messageMap", map);
		}
	}

	/**
	 * 将数据存入session中
	 * 
	 * @param key
	 *            页面调用的值 ${key}
	 * @param value
	 *            与key对应的数据
	 */
	protected void putObjToSession(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	/**
	 * 根据key从session中取出对象数据
	 * 
	 * @param key
	 *            session中的key
	 * @return 与key对应的数据
	 */
	protected Object getObjFromSession(String key) {
		HttpSession session = getSession();
		if (key == null || session == null) {
			return null;
		} else {
			return session.getAttribute(key);
		}
	}

	/**
	 * 从request中取得参数
	 * 
	 * @param key
	 *            页面传递的参数名
	 * @return 参数值，如果传递的为null返回空字符串
	 */
	protected String getParameterFromRequest(String key) {
		String parameter = getRequest().getParameter(key);
		if (parameter == null) {
			parameter = "";
		}
		return parameter;
	}

	/**
	 * 通过ftl模板，action中输出html代码到页面中
	 * 
	 * @param data
	 *            模板中所需要的数据
	 * @param fileName
	 *            模板的文件名
	 * 
	 * @see FreeMarkerEngine
	 * @see StringResult
	 */
	protected String renderHtml(Map<String, Object> data, String fileName) {
		if (fileName != null && !fileName.equalsIgnoreCase(""))
			putObjToContext("result", freeMarkerEngine.getHtml(data,
					getServletContext(), fileName));
		return "renderString";
	}

	/**
	 * action中输出字符串到页面中
	 * 
	 * @param text
	 *            要输出的字符串
	 * 
	 * @see StringResult
	 */
	protected String renderText(String text) {
		if (text != null && !text.equalsIgnoreCase("")) {
			putObjToContext("result", text);
		}
		return "renderString";
	}

	/**
	 * 将action中得到的数据以json格式进行输出，如果对象不存在则输出空字符串
	 * 
	 * @param obj
	 *            要转换成json的对象，只支持自定义类和集合类型
	 * 
	 * @see StringResult
	 */
	protected String renderJson(Object obj) {
		if (obj != null) {
			String json = JsonUtils.buildJsonStr(obj);
			putObjToContext("result", json);
		}
		return "renderString";
	}

	/**
	 * 执行action后跳转到指定的url中，跳转时不带传递任何参数<br>
	 * return redirect("/account/accountList.jsp")
	 * 
	 * @param url
	 *            指定的url路径
	 * @return jspRedirect类型的result
	 * 
	 * @see RedirectResult
	 */
	protected String redirect(String url) {
		String location = "/";
		if (url != null && !url.equalsIgnoreCase("")) {
			location = url;
		}
		putObjToContext("location", location);
		return "jspRedirect";
	}

	/**
	 * 执行action后渲染指定的jsp页面<br>
	 * return dispatcher("/account/accountList.jsp")
	 * 
	 * @param url
	 *            指定的url路径
	 * @return jspDiapatcher类型的result
	 * 
	 * @see DispatcherResult
	 */
	protected String dispatcher(String url) {
		String location = "/";
		if (url != null && !url.equalsIgnoreCase("")) {
			location = url;
		}
		putObjToContext("location", location);
		return "jspDiapatcher";
	}

	/**
	 * 将action链接到另一个指定地址的action中，形成action链。不必写action的后缀<br>
	 * return chain("/account/viewAccount")
	 * 
	 * @param url
	 *            action的路径地址
	 * @return actionChain类型的result
	 * 
	 * @see ChainResult
	 */
	protected String chain(String url) {
		String location = "/";
		if (url != null && !url.equalsIgnoreCase("")) {
			location = url;
		}
		putObjToContext("location", location);
		return "actionChain";
	}

	/**
	 * 验证model的所有属性
	 * 
	 * @param obj
	 *            被验证的model,必须继承自entityDao
	 * 
	 * @see EntityDao#validate()
	 * 
	 */
	@SuppressWarnings("unchecked")
	protected boolean pojoValidate(AbstractIdEntity obj) {
		if (obj == null) {
			return false;
		}
		return handleMsg(validateManager.validate(obj.getClass()));
	}

	/**
	 * 验证model的指定一个属性
	 * 
	 * @param obj
	 *            被验证的model,必须继承自entityDao
	 * @param filed
	 *            指定的属性名
	 * 
	 * @see EntityDao#validate()
	 * 
	 */
	@SuppressWarnings("unchecked")
	protected boolean pojoValidate(AbstractIdEntity obj, String filed) {
		if (obj == null) {
			return false;
		}
		return handleMsg(validateManager.validate(obj.getClass(), filed));
	}

	/**
	 * 验证model后对错误信息的处理，将错误信息保存到messageMap中
	 * 
	 * @param map
	 *            验证后的错误信息
	 * 
	 */
	@SuppressWarnings("unchecked")
	private boolean handleMsg(Map<String, String> map) {
		ActionContext ctx = ActionContext.getContext();
		HashMap<String, String> msg = (HashMap<String, String>) ctx
				.get("messageMap");
		if (msg == null || msg.keySet().size() == 0) {
			msg = (HashMap<String, String>) map;
		} else {
			Iterator<String> it = map.keySet().iterator();
			while (it.hasNext()) {
				String key = it.next();
				msg.put(key, map.get(key));
			}
		}
		ctx.put("messageMap", msg);
		return map.keySet().size() > 0;
	}

	/**
	 * 根据map中的数据来拼接查询的链接<br>
	 * pageLinkToContext("/account/viewAccount.action",map)
	 * 
	 * @param actionName
	 *            action的名称
	 * @param map
	 *            链接中的数据和参数名
	 * 
	 * @see ApplicationHelper#buildSearchLink(Map)
	 */
	protected void pageLinkToContext(String actionName, Map<String, Object> map) {
		StringBuffer sb = new StringBuffer();
		sb.append(actionName).append("?");
		sb.append(ApplicationHelper.buildSearchLink(map));
		putObjToContext("pageLink", sb.toString());
	}

}
